#ifndef BOSS_Afterburner_BranchPlotOptions_H
#define BOSS_Afterburner_BranchPlotOptions_H

#include "Containers/AxisNamed.h"
#include "Containers/NamedObject.h"
#include "TH1.h"
#include "TString.h"
#include "TTimeStamp.h"
#include <string>
#include <vector>
#include <yaml-cpp/yaml.h>

/// @addtogroup Afterburner_objects
/// @{

/// This object is used as a container of information you need to plot a branch or a collection of branches using the `TTree::Draw` method.
/// @author   Remco de Boer 雷穆克 (r.e.deboer@students.uu.nl or remco.de.boer@ihep.ac.cn)
/// @date     March 24th, 2019
class BranchPlotOptions : public NamedObject
{
public:
  BranchPlotOptions() {}
  BranchPlotOptions(const TString& input);
  BranchPlotOptions(const YAML::Node& input);

  bool IsOK() const;
  bool IsWrite() const { return fOutputFileName.Length(); };
  void Print() const;

  bool Import(TString input);
  bool Import(const YAML::Node& input);
  bool AddBranch(const TString& input);
  bool AddBranch(const YAML::Node& input);

  void SetCutSelection(const TString& selection);
  void SetCutSelection(const YAML::Node& input);
  void SetDrawOptions(TString input);
  void SetDrawOptions(const YAML::Node& input);
  void SetTreeName(const TString& treename);
  void SetOutputFileName(const TString& filename);
  void SetOutputFileName(const YAML::Node& input);
  void SetNoLog();

  const size_t GetNBranches() const { return fListOfAxes.size(); }
  AxisNamed&   operator[](size_t i) { return fListOfAxes[i]; }

  void SetAxisLabels(TH1* hist) const;
  void SetPlotLabel(TH1* hist) const;

  const char* OutputFileName() const { return fOutputFileName.Data(); }
  const char* TreeName() const { return fTreeName.Data(); }
  const char* VarExp() const;
  const char* CutSelection() const { return fCutSelection.Data(); }
  const char* DrawOption() const { return fDrawOption.Data(); }
  bool        LogX() const { return fSetLog[0]; }
  bool        LogY() const { return fSetLog[1]; }
  bool        LogZ() const { return fSetLog[2]; }
  bool        HasLogScale() const;
  std::string BuildOriginalString() const;
  std::string BuildHistName() const;
  std::string LogXYZ() const;

private:
  TString                fTreeName;
  TString                fCutSelection; /// @todo Rewrite in terms of [`TCut`](https://root.cern.ch/doc/master/classTCut.html)
  TString                fDrawOption;
  TString                fOutputFileName;
  std::vector<bool>      fSetLog{false, false, false};
  std::vector<AxisNamed> fListOfAxes;
  bool                   fIsOK{false};
  TTimeStamp             fID;

  const bool ImportWarning(const TString& input, const TString& message,
                           const bool notOK = true) const;
  const bool Tokenize(const TString& input, TString& tok, Ssiz_t& start,
                      const char* delim = ";") const;
};

/// @}
#endif